package org.suburban.servlet.schedule;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.WARNING;
import static org.suburban.resource.RequestParams.*;
import java.io.IOException;
import java.io.StringReader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.suburban.servlet.ClientServlet;

/**
 * Super class to implement basic functionality for all
 * schedule servlets. 
 *
 * @author Alexey Palamarchuk (slonnik@gmail.com)
 */
@SuppressWarnings("serial")
abstract class ScheduleServlet extends ClientServlet{
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		/** call super class method*/
		super.doPost(req, resp);
										
		/**
		 * Attention: query should be in the following format
		 * 
		 * http://m.rasp.yandex.ru/suburban_search?station_from=<departure>&station_to=<arrival>
		 * 
		 */
		String direction = req.getParameter(DIRECTION);
		if(direction == null)
		{
			logger.log(WARNING, "'Direction' request parameter is missing in client request.");
		}
		
		String departure = req.getParameter(DEPARTURE);
		if(departure == null)
		{
			logger.log(WARNING, "'Departure' request parameter is missing in client request.");
		}
		
		String arrival = req.getParameter(ARRIVAL);
		if(departure == null)
		{
			logger.log(WARNING, "'Arrival' request parameter is missing in client request.");
		}
		
		boolean isXml = Boolean.parseBoolean(req.getParameter(IS_XML));
		boolean isEmail = Boolean.parseBoolean(req.getParameter(IS_EMAIL));
		
		String request = getHTTPRequest(direction, departure, arrival);
		String header = scheduleName;
						
		if(logger.isLoggable(FINE))
		{
			logger.log(FINE, "Outgoing HTTP request is: {0}", request);
		}
		
		String text = fetchURL(request, "UTF-8");
        int start = text.lastIndexOf("<ul");
        int end = text.lastIndexOf("</ul");
        logger.log(FINE, "Start = {0} end = {1}", new Object[] {start, end});
        text = text.substring(start, end) + "</ul>";
        
        /** trace output*/
        if(logger.isLoggable(FINE))
        {
        	logger.log(FINE, "HTML Output: {0}", text);
        }
        
		/** let's parse*/
        StringBuilder out = new StringBuilder();
        try
		{
			
           	SAXParserFactory factory = SAXParserFactory.newInstance();
	        factory.newSAXParser().parse(new InputSource(new StringReader(text)),
	        		getScheduleCracker(out, header, isXml));
		}
		catch(ParserConfigurationException ex)
		{
			logger.log(WARNING,"Failed to parse HTML response: {}", ex.getMessage());
			return;
		}
		catch(SAXException ex)
		{
			logger.log(WARNING,"Failed to parse HTML response: {}", ex.getMessage());
			return;
		}
		/** send outgoing result to originator*/
		if(isEmail)
		{
			sendEmailMessage(header, out.toString(), client, originator);
			
		}
		else
		{
			sendMessage(out.toString(), client, originator);
		}
	}
	
	/**
	 * create HTTP request
	 * @param direction		- direction
	 * @param departure		- departure code
	 * @param arrival		- arrival code
	 * @return HTTP request
	 */
	abstract String getHTTPRequest(String direction, String departure, String arrival);
	/**
	 * create HTML response cracker
	 * @param out	- output stream for to publish parsing data	
	 * @param header - schedule header
	 * @param isXml - true if schedule should be XML formated, otherwise false
	 * @return HTML cracker
	 */
	abstract ScheduleCracker getScheduleCracker(StringBuilder out, String header, boolean isXml);
}
